﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;

namespace VDataAdapter.Communication
{
    public struct MessageStockTest
    {
        public PriceLibrary.PriceService.StockInfoStatic stockInfoStatic;
        public PriceLibrary.PriceService.StockInfoDyns newObj;
        public PriceLibrary.PriceService.StockInfoDyns oldObj;
        public string msg;
    }

    public struct MessageTransactionTest
    {
        public PriceLibrary.ChartService.Transaction newObj;
        public PriceLibrary.ChartService.Transaction oldObj;
        public string msg;
    }

    public struct MessagePutThroughTest
    {
        public PriceLibrary.PriceService.StockInfoStatic objStatic;
        public PriceLibrary.PriceService.StockInfoDyns objNew;
        public PriceLibrary.PriceService.StockInfoDyns objOld;
        public string msg;
        public TransactionType transType;
    }

    public struct MessageTransactionPutThroughTest
    {
        public PriceLibrary.PriceService.Transaction objNew;
        public PriceLibrary.PriceService.Transaction objOld;
        public string msg;
    }

    public struct MessageMarketTest
    {
        public PriceLibrary.PriceService.MarketInfo objNew;
        public PriceLibrary.PriceService.MarketInfo objOld;
        public string msg;
    }

    /// <summary>
    /// This class serialize all actions of MessageBuilder to file
    /// in order to recover and unit test later
    /// </summary>
    public class MessageBuilderRecorder
    {
        /// <summary>
        /// return "BuildMessageStock.test"
        /// </summary>
        public const string BUILD_MESSAGE_STOCK_FILENAME = "BuildMessageStock.test";
        
        public const string BUILD_MESSAGE_TRANSACTION_FILENAME = "BuildMessageTransaction.test";

        public const string BASEPRICES = "basePrices.test";

        public string BUILD_MESSAGE_PUTTHROUGH_FILENAME
        {
            get { return "BuildMessagePutThrough.test"; }
        }

        public string BUILD_MESSAGE_MARKET_FILENAME
        {
            get { return "BuildMessageMarket.test"; }
        }

        public string BUILD_MESSAGE_PUTTHROUGH_TRANSACTION_FILENAME
        {
            get{return "BuildMessagePutThroughTransaction.test";}
        }

        protected PriceServerObjectFile _fileWriter = new PriceServerObjectFile();

        public MessageBuilderRecorder()
        {          

        }

        /// <summary>
        /// For unit test purpose
        /// Write down a DataSource to use in Build Message Transaction etc
        /// </summary>
        /// <param name="dataSource"></param>
        public void WriteDataSourceStockbase(DataSource dataSource)
        {
            string filepath = BASEPRICES;
            _fileWriter.WriteToFile(filepath, new Object[] { dataSource.BasePrices });
        }

        public Dictionary<string, PriceLibrary.PriceService.StockBase> ReadDataSourceStockBase(string filepath)
        {
            Stream stream;
            try
            {
                Dictionary<string, PriceLibrary.PriceService.StockBase> result;
                stream = File.Open(filepath, FileMode.Open);
                result = (Dictionary<string, PriceLibrary.PriceService.StockBase>)_fileWriter.ReadFromStream(stream);
                stream.Close();
                return result;
            }
            catch (FileNotFoundException ex)
            {
                throw new IOException("Cannot file DataSource file in path: " + ex.FileName, ex);
            }
            catch (Exception ex)
            {
                throw new Exception("Error load DataSource file", ex);
            }
        }

        /// <summary>
        /// For unit test purpose
        /// Mapped with MessageBuilder.BuildMessageStock
        /// </summary> 
        public void WriteBuildMessageStock(PriceLibrary.PriceService.StockInfoStatic stockInfoStatic,
                        PriceLibrary.PriceService.StockInfoDyns newObj,
                        PriceLibrary.PriceService.StockInfoDyns oldObj,
                        string msg)
        {
            string filepath = BUILD_MESSAGE_STOCK_FILENAME;
            _fileWriter.WriteToFile(filepath, new Object[] { stockInfoStatic, newObj, oldObj, msg }); 
        }

        public List<MessageStockTest> GetMessageStockList(string filepath)
        {
            Stream stream = File.Open(filepath, FileMode.Open);
            List<MessageStockTest> result = new List<MessageStockTest>();

            while (stream.Position < stream.Length)
            {
                MessageStockTest messageStock;                 
                messageStock.stockInfoStatic = (PriceLibrary.PriceService.StockInfoStatic)_fileWriter.ReadFromStream(stream);
                messageStock.newObj = (PriceLibrary.PriceService.StockInfoDyns)_fileWriter.ReadFromStream(stream);
                messageStock.oldObj = (PriceLibrary.PriceService.StockInfoDyns)_fileWriter.ReadFromStream(stream);
                messageStock.msg = (string)_fileWriter.ReadFromStream(stream);
                result.Add(messageStock);                
            }
            
            stream.Close();

            return result;
        }

        /// <summary>
        /// For unit test purpose
        /// mapped with MessageBuilder.BuildMessageTransaction
        /// </summary>        
        public void WriteBuildMessageTransaction(PriceLibrary.ChartService.Transaction objNew,
                                        PriceLibrary.ChartService.Transaction objOld, string str)
        {
            string filepath = BUILD_MESSAGE_TRANSACTION_FILENAME;
            _fileWriter.WriteToFile(filepath, new Object[] { objNew, objOld, str });
            //Stream stream = InitFileStream(filepath);

            // 
            //formatter.Serialize(stream, objNew);
            //formatter.Serialize(stream, objOld);
            //formatter.Serialize(stream, str);
            //stream.Close();
        }

        public List<MessageTransactionTest> GetMessageTransactionList(string filepath)
        {
            Stream stream = Stream.Null;
            try
            {
                stream = File.Open(filepath, FileMode.Open);
            }
            catch (IOException ex)
            {
                throw new IOException("Error loading message transaction list", ex);
            }
  
            List<MessageTransactionTest> result = new List<MessageTransactionTest>();

            try
            {
                while (stream.Position < stream.Length)
                {
                    MessageTransactionTest messageTransaction;

                    messageTransaction.newObj = (PriceLibrary.ChartService.Transaction)_fileWriter.ReadFromStream(stream);
                    messageTransaction.oldObj = (PriceLibrary.ChartService.Transaction)_fileWriter.ReadFromStream(stream);
                    messageTransaction.msg = (string)_fileWriter.ReadFromStream(stream);
                    result.Add(messageTransaction);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error reading from stream when trying to get message transaction list from file", ex);
            }
            finally
            {
                stream.Close();
            }                
            
            return result;
        }

        public void WriteBuildMessagePutThrough(PriceLibrary.PriceService.StockInfoStatic objStatic,
            PriceLibrary.PriceService.StockInfoDyns objNew,
            PriceLibrary.PriceService.StockInfoDyns objOld, string msg, TransactionType transType)
        {
            string filepath = BUILD_MESSAGE_PUTTHROUGH_FILENAME;
            _fileWriter.WriteToFile(filepath, new Object[] { objNew, objOld, msg, transType });
        }
        
        public List<MessagePutThroughTest> GetMessagePutThroughList(string filepath)
        {
            Stream stream = File.Open(filepath, FileMode.Open);
            List<MessagePutThroughTest> result = new List<MessagePutThroughTest>();

            while (stream.Position < stream.Length)
            {
                MessagePutThroughTest messagePutThrough;
                 
                messagePutThrough.objStatic = (PriceLibrary.PriceService.StockInfoStatic)_fileWriter.ReadFromStream(stream);
                messagePutThrough.objNew = (PriceLibrary.PriceService.StockInfoDyns)_fileWriter.ReadFromStream(stream);
                messagePutThrough.objOld = (PriceLibrary.PriceService.StockInfoDyns)_fileWriter.ReadFromStream(stream);
                messagePutThrough.msg = (string)_fileWriter.ReadFromStream(stream);
                messagePutThrough.transType = (TransactionType)_fileWriter.ReadFromStream(stream);
                result.Add(messagePutThrough);
            }

            return result;
        }

       

        public void WriteBuildMessageTransactionPutThrough(PriceLibrary.PriceService.Transaction objNew,
        PriceLibrary.PriceService.Transaction objOld, string msg)
        {
            string filepath = BUILD_MESSAGE_PUTTHROUGH_TRANSACTION_FILENAME;
            _fileWriter.WriteToFile(filepath, new Object[] { objNew, objOld, msg });      
        }

        public List<MessageTransactionPutThroughTest> GetMessageTransactionPutThroughList(string filepath)
        {
            Stream stream = File.Open(filepath, FileMode.Open);
            List<MessageTransactionPutThroughTest> result = new List<MessageTransactionPutThroughTest>();

            while (stream.Position < stream.Length)
            {
                MessageTransactionPutThroughTest messagePutThrough;
                 
                messagePutThrough.objNew = (PriceLibrary.PriceService.Transaction)_fileWriter.ReadFromStream(stream);
                messagePutThrough.objOld = (PriceLibrary.PriceService.Transaction)_fileWriter.ReadFromStream(stream);
                messagePutThrough.msg = (string)_fileWriter.ReadFromStream(stream);
                result.Add(messagePutThrough);
            }

            return result;
        }

        public void WriteBuildMessageMarket(PriceLibrary.PriceService.MarketInfo objNew,
            PriceLibrary.PriceService.MarketInfo objOld, string msg)
        {
            string filepath = BUILD_MESSAGE_MARKET_FILENAME;

            _fileWriter.WriteToFile(filepath, new Object[] { objNew, objOld, msg }); 
        }

        public List<MessageMarketTest> GetMessageMarketList(string filepath)
        {
            Stream stream = File.Open(filepath, FileMode.Open);
            List<MessageMarketTest> result = new List<MessageMarketTest>();

            while (stream.Position < stream.Length)
            {
                MessageMarketTest messageMarket;
                 
                messageMarket.objNew = (PriceLibrary.PriceService.MarketInfo)_fileWriter.ReadFromStream(stream);
                messageMarket.objOld = (PriceLibrary.PriceService.MarketInfo)_fileWriter.ReadFromStream(stream);
                messageMarket.msg = (string)_fileWriter.ReadFromStream(stream);
                result.Add(messageMarket);
            }

            return result;
        }
    }
}
